package co.edu.unal.franquicias.visa.auth;

import com.sun.jersey.api.NotFoundException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Class that manages the application data in an in-memory map.
 */
public class DataProvider {
    private static final Map<String, Map<Integer, Status>> statuses = new HashMap<String, Map<Integer, Status>>();
    private static final Map<String, User> users = new HashMap<String, User>();
    private static AtomicInteger lastId = new AtomicInteger(0);

    /**
     * Gets a collection of all statuses for a given user.
     *
     * @param user user name
     * @return collection of all statuses for the user
     */
    public static synchronized Collection<Status> getStatuses(String user) {
        Map<Integer, Status> userStatuses = statuses.get(user);
        if (userStatuses != null) {
            return new ArrayList(userStatuses.values());
        } else {
            return Collections.emptyList();
        }
    }

    /**
     * Generates a new unique status ID
     *
     * @return unique status ID
     */
    public static int makeNewId() {
        return lastId.incrementAndGet();
    }

    /**
     * Creates a new status and stores it in the map.
     *
     * @param user user the new status belongs to
     * @param text status text
     * @return ID of the newly created status
     */
    public static synchronized int createStatus(String user, String text) {
        Status status = new Status();
        status.id = DataProvider.makeNewId();
        status.text = text;
        status.createdAt = new Date().toString();
        status.user = getUser(user);
        Map<Integer, Status> userNotes = statuses.get(user);
        if (userNotes == null) {
            userNotes = new HashMap<Integer, Status>();
            statuses.put(user, userNotes);
        }
        userNotes.put(status.getId(), status);
        return status.getId();
    }

    /**
     * Retrieves status by ID for a given user.
     *
     * @param user owner of the status to retrieve
     * @param id ID of the status to retrieve
     * @return object representing the status
     * @throws NotFoundException thrown if the status was not found
     */
    public static synchronized Status getStatus(String user, int id) throws NotFoundException {
        Map<Integer, Status> userStatuses = statuses.get(user);
        if (userStatuses == null || !userStatuses.containsKey(id)) {
            throw new NotFoundException();
        }
        return userStatuses.get(id);
    }

    /** Updates a status.
     *
     * @param user owner of the status
     * @param statusId ID of the status
     * @param text new text of the status
     * @throws NotFoundException thrown if the status was not found
     */
    public static synchronized void updateStatus(String user, int statusId, String text) throws NotFoundException {
        Map<Integer, Status> userStatuses = statuses.get(user);
        if (userStatuses == null || !userStatuses.containsKey(statusId)) {
            throw new NotFoundException();
        }
        Status status = userStatuses.get(statusId);
        status.text = text;
    }

    /**
     * Deletes a status.
     *
     * @param user owner of the status
     * @param statusId status ID
     * @throws NotFoundException thrown if the status was not found
     */
    public static void deleteStatus(String user, int statusId) throws NotFoundException {
        Map<Integer, Status> userStatuses = statuses.get(user);
        if (userStatuses == null || userStatuses.remove(statusId) == null) {
            throw new NotFoundException();
        }
    }

    private static User getUser(String name) {
        User user = users.get(name);
        if (user == null) {
            user = new User();
            user.name = name;
            users.put(name, user);
        }
        return user;
    }
}
